import {ChangeDetectorRef, Component, ComponentFactoryResolver, OnInit, ViewChild} from '@angular/core';

import {PrizeDoService} from '../prize-do.service';
import {EmployeeComponent} from '../employee/employee.component';
import {ContainerDirective} from './container.directive';
import {ElectronService} from 'ngx-electron';

@Component({
  selector: 'prize-prize-do',
  templateUrl: './prize.component.html',
  styleUrls: ['./prize.component.css']
})
export class PrizeComponent implements OnInit {

  @ViewChild(ContainerDirective)
  private container: ContainerDirective;
  isDoing: boolean;

  employees: any;
  private timers: any[];
  selectedOption;
  options;
  index: number;
  employeeRand: any[];
  isStopping = false;
  isShowModal = false;
  results: any[];
  style: any = {
    top: 'calc(50% - 200px)'
  };
  private stopTimes: number;
  isShowResModal = false;
  private stopTimeCount: number;
  private employeeCompMap: Map<string, { comp: EmployeeComponent, index: number }>;

  private interval = 30;
  currStatus: string;
  canStop = false;
  private pathSep: string;

  constructor(private _electronService: ElectronService,
              private prizeDoService: PrizeDoService,
              private componentFactoryResolver: ComponentFactoryResolver,
              private ref: ChangeDetectorRef) {
  }

  ngOnInit() {
    // this.init();
    // const ipcRenderer = this._electronService.ipcRenderer;
    // ipcRenderer.on('init-prize', (event, arg) => {
    //   console.log(arg);
    //   this.init();
    //   this.ref.detectChanges();
    // });
    this.pathSep = this._electronService.remote.require('path').sep;
  }

  private init() {
    this.employees = this.prizeDoService.employees;
    this.options = this.prizeDoService.prizes;
    this.employeeCompMap = new Map();
    this.showEmployee(this.employees);
    this.results = [];
    this.timers = [];
    this.stopTimers();

  }

  showEmployee(employees) {
    if (this.employeeCompMap.size === 0) {
      const componentFactory = this.componentFactoryResolver.resolveComponentFactory(EmployeeComponent);
      this.container.viewContainerRef.clear();
      employees.forEach((e, index) => {
        const componentRef = this.container.viewContainerRef.createComponent(componentFactory).instance;
        componentRef.data = e;
        componentRef.index = index;
        this.employeeCompMap.set(e[0], {comp: componentRef, index: index});
      });
    } else {
      employees.forEach((e, index) => {
        const emp = this.employeeCompMap.get(e[0]);
        if (emp) {
          emp.comp.data = e;
          emp.comp.index = index;
        }
      });
    }
  }

  doIt($event) {

    this.isDoing = true;
    const onceTime = 1000;
    const timesRand = 5;
    for (let i = 0; i < 5; i++) {
      setTimeout(() => {
        this.randAndShow();
      }, onceTime * i);
    }
    setTimeout(() => {
      this.canStop = true;
      this.hideNames();
      this.startLottery();
    }, onceTime * timesRand);
  }

  private randAndShow() {
    this.employeeRand = [];
    this.randEmployees(this.employeeRand);
    this.showEmployee(this.employeeRand);
  }

  private startLottery() {
    this.index = 0;
    this.lottery();
    this.timers.push(setInterval(() => {
      this.lottery();
    }, this.interval));
  }

  private lottery() {
    if (this.index > 0) {
      if (this.employeeRand[this.index - 1]) {
        this.employeeRand[this.index - 1][2] = false;
      }

    } else if (this.index === 0) {
      if (this.employeeRand[this.employees.length - 1]) {
        this.employeeRand[this.employees.length - 1][2] = false;
      }
    }
    if (this.employeeRand[this.index]) {
      this.employeeRand[this.index][2] = true;
    }


    this.index++;
    if (this.index >= this.employees.length) {
      // this.stopTimers();
      // setTimeout(() => {
      //   if (this.employeeRand[this.index - 1]) {
      //     this.employeeRand[this.index - 1][2] = false;
      //   }
      //   this.startLottery(isStopping);
      // }, this.interval);
      this.index = 0;
    }
  }

  private randEmployees(employeeRand: any[]) {
    const randIndex = [];
    const oriIndex = [];
    this.employees.forEach((e, index) => {
      const numRand = Math.floor((Math.random() * this.employees.length));
      randIndex.push(numRand);
      oriIndex.push(index);
    });
    // console.log(oriIndex, randIndex);
    this.employees.forEach((e, index) => {
      const temp = oriIndex[index];
      oriIndex[index] = oriIndex[randIndex[index]];
      oriIndex[randIndex[index]] = temp;
    });
    oriIndex.forEach(v => {
      employeeRand.push(this.employees[v]);
    });
    return oriIndex;
  }

  stopIt($event) {
    this.isStopping = true;
    this.stopTimers();
    setTimeout(() => {
      this.stopTimers();
      this.stopTimes = Math.floor(Math.random() * 30) + 5;
      this.stopTimeCount = this.getTimeCount();
      this.stopTime(this.stopTimes);

    }, 100);

  }

  getTimeCount() {
    let count = 0;
    for (let i = 1; i <= this.stopTimes; i++) {
      count += i;
    }
    return count;
  }

  stopTime(times) {
    setTimeout(() => {
      this.lottery();
      times--;
      if (times > 0) {
        this.stopTime(times);
      } else {
        this.isDoing = false;
        this.isStopping = false;
        this.isShowModal = true;
        this.canStop = false;
      }
    }, 20 + (6000 / this.stopTimeCount) * (this.stopTimes - times));
  }


  handleCancel($event: MouseEvent | KeyboardEvent) {
    this.isShowModal = false;
    this.employeeRand[this.getIndex()][2] = false;
    this.showNames();
  }


  getIndex() {
    return this.index === 0 ? this.employeeRand.length - 1 : this.index - 1;
  }

  handleOk($event) {
    this.isShowModal = false;
    setTimeout(() => {
      const index = this.getIndex();
      this.results.push(this.employeeRand[index][1] + ' ' + this.selectedOption);
      const emp = this.employeeCompMap.get(this.employeeRand[index][0]);
      this.employeeRand.splice(index, 1);
      emp.comp.hide = true;
      this.employees = this.employeeRand;
      this.showEmployee(this.employeeRand);
      this.saveRes(this.results);
      this.showNames();
    }, 500);

  }

  saveRes(res) {
    const fs = this._electronService.remote.require('fs');
    fs.writeFile(this.prizeDoService.dataPath + this.pathSep + 'res.txt', res.join('\r\n'), (err) => {
      if (err) {
        throw err;
      }
      console.log('The file has been saved!');
    });
  }

  hasEmployees() {
    return this.employees && this.employees.length > 1;
  }

  selectDataPath($event) {
    const dialog = this._electronService.remote.dialog;
    dialog.showOpenDialog({
      // filters: [{name: 'csv', extensions: ['csv', 'txt']}],
      properties: ['openDirectory']
    }, (path) => {
      const fs = this._electronService.remote.require('fs');
      this.prizeDoService.dataPath = path[0];
      const inputNameFile = path[0] + this.pathSep + 'names.xlsx';
      console.log(inputNameFile);
      const XLSX = this._electronService.remote.require('xlsx');
      const workbook = XLSX.readFile(inputNameFile);
      this.prizeDoService.employees = XLSX.utils.sheet_to_json(workbook.Sheets['Sheet1'], {header: 1});
      const inputPrizeFile = path[0] + this.pathSep + 'prizes.xlsx';
      const workbookPrize = XLSX.readFile(inputPrizeFile);
      this.prizeDoService.prizes = XLSX.utils.sheet_to_json(workbookPrize.Sheets['Sheet1'], {header: 1}).map(e => e[0]);
      // console.log(this.prizeDoService.employees, this.prizeDoService.prizes);
      this.init();
      this.ref.detectChanges();
    });

  }

  private hideNames() {
    this.employeeCompMap.forEach(emp => {
      emp.comp.showName = false;
    });
  }

  private showNames() {
    this.employeeCompMap.forEach(emp => {
      emp.comp.showName = true;
    });
  }

  private stopTimers() {
    this.timers.forEach(t => {
      clearInterval(t);
    });
    this.timers = [];
  }
}
